package it.softphone.cmc.server.rest;

import it.softphone.cmc.server.service.QueryTask;
import it.softphone.cmc.server.service.exception.CMCException;
import it.softphone.cmc.shared.entity.Account;
import it.softphone.cmc.shared.entity.TenantUser;
import it.softphone.cmc.shared.security.Permissions;
import it.softphone.cmc.shared.security.Roles;
import it.softphone.commons.json.server.JSONException;
import it.softphone.commons.json.server.jersey.JSONParam;

import java.util.Collections;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.apache.shiro.authz.annotation.RequiresPermissions;

/**
 * 
 * @author bsorrentino
 *
 */
@Path("/user")
public class CMCUserManager extends RESTServiceAware  {

	/**
	 * 
	 * @author bsorrentino
	 *
	 */
	public static class  Result implements TenantUser.ResultSet {

		java.util.List<TenantUser> result ;
		
		@Override
		public List<TenantUser> getResult() {
			return result;
		}

		@Override
		public void setResult(List<TenantUser> result) {
			// MAKE A COPY
			this.result = new java.util.ArrayList<TenantUser>( result );
		}
		
	}

	@GET
	@Produces(MediaType.APPLICATION_JSON)
	@Path("all")
	public it.softphone.commons.json.server.JSONObject getAllUsers() throws CMCException 
	{
		
		if( !security().hasRole(Roles.ADMINISTRATOR) )
			checkPermission( Permissions.User.SELECT );

		final Result result = new Result();

		system().find( "SELECT r FROM UserEntity r", null,  new QueryTask<List<TenantUser>>() {

					@Override
					public void run(List<TenantUser> list) throws Exception {
						
						if( list==null ) {
							list = Collections.emptyList();
						}
						result.setResult( list );
						
					}
					
				});
			
		
				
			it.softphone.commons.json.server.JSONObject o = new it.softphone.commons.json.server.JSONObject( result );
			
			return o;
	}
	
	@POST
	@Path("register")
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Response registerUserInTenant( @FormParam("tenant") String tenant, MultivaluedMap<String, String> extraAttributes ) throws CMCException
	{
	
		final String currentTenant = tenant().getCurrentTenant();

		if( currentTenant.equals(tenant().getSystemTenant()) ){
			
			checkRole( Roles.ADMINISTRATOR );
		}
		else {
			checkRole( Roles.GUEST );
		}
		
		final Account loggedAccount = getloggedAccount();
		
		
		if( loggedAccount == null ) {
			throw new CMCException( "account is not logged in!");
		}
		
		if( loggedAccount.getUser() != null ) {
			throw new CMCException( String.format( "logged account [%s] already ha registerd user in given tenant [%s]", loggedAccount.getId(),  tenant().getCurrentTenant() ));
			
		}
		
		final TenantUser newUser = system().makeUser();
		
		newUser.getPermissions().add( Permissions.Script.EXEC );
		
		newUser.setId( loggedAccount.getId() );
		newUser.setTenant( currentTenant );

		if( extraAttributes != null  && !extraAttributes.isEmpty() ) {

			it.softphone.commons.json.server.JSONObject attrMap = newUser.encodeAttributes();
			
			for( String key : extraAttributes.keySet() ) {
				
					attrMap.put( key, extraAttributes.getFirst(key) );
			}
			
			newUser.decodeAttributes(attrMap);
		}
		
		
		final boolean enableUser = true;

		
		system().createUser(newUser, loggedAccount, enableUser);
			
				
		return Response.ok().build();
		
		
	}

	@POST
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	@Produces(MediaType.APPLICATION_JSON)
	@RequiresPermissions( Permissions.User.CREATE )
	public it.softphone.commons.json.server.JSONObject registerUserInTenantWithouAccount(	@FormParam("user") @DefaultValue("{}") JSONParam param )  throws CMCException 
	{
		TenantUser newUser;
		try {
			newUser = system().makeUserFromJson(param.toObject());
		} catch (JSONException e) {
			throw new CMCException(e);
		}

		final String currentTenant = tenant().getCurrentTenant();
	
		newUser.getPermissions().add( Permissions.Script.EXEC );
		newUser.setTenant( currentTenant );

		final boolean enableUser = false;
		final Account relatedAccount = null;
		
		system().createUser(newUser, relatedAccount, enableUser);

		return new it.softphone.commons.json.server.JSONObject(newUser);
			
			
		
	}
	
	@PUT
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	@RequiresPermissions( Permissions.User.UPDATE )
	public Response updateUserInTenant(	@FormParam("user") @DefaultValue("{}") JSONParam param ) throws CMCException
	{
		throw new CMCRestException( Status.SERVICE_UNAVAILABLE, "service is not implemente yet!");
	}
	
	@DELETE
	@Consumes(MediaType.TEXT_PLAIN)
	@RequiresPermissions( Permissions.User.DELETE )
	public Response removeUserFromTenant( @FormParam("user") @DefaultValue("{}") JSONParam param ) throws CMCException 
	{
		throw new CMCRestException( Status.SERVICE_UNAVAILABLE, "service is not implemente yet!");
	}
}
